﻿///////////////////////////////////////////////////////////////////////////////
//
// This file is part of the BassDrop project
//   https://code.google.com/p/bass-drop/
//
//
// Creator:	Gergely Krajcsovszki (krajcsovszkig@hotmail.com)
// Date:	2013-11-03 11:45
//
//
// Copyright © 2013-2014. Gergely Krajcsovszki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace BassDrop.DesktopClient.UI.Controls
{
	/// <summary>
	/// A TextBlock-like control, that<para/>
	///		- automatically scrolls left and right if the text is longer than fitting<para/>
	///		- optionally has a tooltip displayed in this case as well
	/// </summary>
	public partial class AutoScrollTextBlock : UserControl
	{
		public AutoScrollTextBlock()
		{
			InitializeComponent();

			timer.Elapsed += timer_Elapsed;
		}

		/// <summary>
		/// Timer to tick the update intervals for the scrolling
		/// </summary>
		private Timer timer = new Timer( 1000.0 / 30.0 ); // 30 FPS

		/// <summary>
		/// The signed amount to scroll in the next iteration in pixels
		/// </summary>
		private int scrollDelta = 0;

		/// <summary>
		/// Does the content need to be scrolled
		/// </summary>
		private bool scrolling = false;

		/// <summary>
		/// The time when scrolling finished and waiting to scroll back started
		/// </summary>
		private DateTime waitingStarted;

		/// <summary>
		/// Gets the inner TextBlock of this component
		/// </summary>
		public TextBlock TextBlock
		{
			get
			{
				return textBlock;
			}
		}

		/// <summary>
		/// Gets or sets the text displayed by this component<para />
		/// <para />
		/// Always set the text through this property, otherwise the scrolling won't update!
		/// </summary>
		public string Text
		{
			get
			{
				return TextBlock.Text;
			}
			set
			{
				TextBlock.Text = value;

				UpdateTextBlockLayout();
			}
		}

		/// <summary>
		/// Gets or sets the Style of the TextBlock of this component
		/// </summary>
		public Style TextBlockStyle
		{
			get
			{
				return TextBlock.Style;
			}
			set
			{
				TextBlock.Style = value;
			}
		}

		/// <summary>
		/// Amount of scrolling in a second in pixels
		/// </summary>
		private int scrollingSpeed = 10;

		/// <summary>
		/// Amount of scrolling in a second in pixels
		/// </summary>
		public int ScrollingSpeed
		{
			get
			{
				return scrollingSpeed;
			}
			set
			{
				scrollingSpeed = value;
			}
		}

		/// <summary>
		/// Amount of time to wait before starting to scroll in the opposite direction
		/// when the end is reached in milliseconds. Rounded up to the animation resolution
		/// (30 FPS).
		/// </summary>
		private int scrollBackDelay = 1000;

		/// <summary>
		/// Amount of time to wait before starting to scroll in the opposite direction
		/// when the end is reached in milliseconds. Rounded up to the animation resolution
		/// (30 FPS).
		/// </summary>
		public int ScrollBackDelay
		{
			get
			{
				return scrollBackDelay;
			}
			set
			{
				scrollBackDelay = value;
			}
		}

		/// <summary>
		/// Enable / disable showing a tooltip automatically, if the text is too long
		/// </summary>
		private bool showToolTip = true;

		/// <summary>
		/// Enable / disable showing a tooltip automatically, if the text is too long
		/// </summary>
		public bool ShowToolTip
		{
			get
			{
				return showToolTip;
			}
			set
			{
				showToolTip = value;

				UpdateToolTip();
			}
		}

		/// <summary>
		/// Updates the scrolling and ToolTip visibility of the TextBlock
		/// </summary>
		private void UpdateTextBlockLayout()
		{
			if ( TextBlock.Width > this.Width )
			{
				EnableScrolling();
			}
			else
			{
				DisableScrolling();
			}

			UpdateToolTip();
		}

		/// <summary>
		/// Disables auto scrolling
		/// </summary>
		private void DisableScrolling()
		{
			scrolling = false;
		}

		/// <summary>
		/// Enables auto scrolling
		/// </summary>
		private void EnableScrolling()
		{
			scrolling = true;

			waitingStarted = DateTime.Now;
		}

		/// <summary>
		/// Timer tick event, performs the scrolling
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void timer_Elapsed( object sender, ElapsedEventArgs e )
		{
			throw new NotImplementedException(); // TODO: timer_Elapsed()
			// Animation?!
			// LayoutTransformot kell nyomogatni
			/*
			 * Eltolás
			 * Ellenőrzés, hogy kész-e
			 * Új eltolás beállítása
			 * Ha kész, waitingStarted beállítása
			 * Ha waitingStarted lejárt, mozgatás másik irányba
			 * Thread race waitingStarteden?! többin?
			 */
		}

		/// <summary>
		/// Updates the content and visibility of the ToolTip
		/// </summary>
		private void UpdateToolTip()
		{
			if ( scrolling && ShowToolTip )
			{
				TextBlock.ToolTip = TextBlock.Text;
			}
			else
			{
				TextBlock.ToolTip = null;
			}
		}
	}
}
